package com.example.websocketclusterspringbootstarter.process;

import com.alibaba.fastjson.JSON;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.example.websocketclusterspringbootstarter.event.BaseEventWrapper;
import com.example.websocketclusterspringbootstarter.factoty.EventHandlerFactory;
import com.example.websocketclusterspringbootstarter.helper.TransferHelper;
import com.example.websocketclusterspringbootstarter.utils.LocalCacheUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * ws事件处理统一处理器
 *
 * @author zhucc
 * @date 2022-03-08
 */
@Component
@Slf4j
public class WsEventHandler {

    public static final String NODE_NAME = "zhucc-node";

    public static final String EVENT_NAME = "eventName";
    public static final String FROM = "from";
    public static final String TO = "to";

    @Value("${nodeName}")
    private String nodeName;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private TransferHelper transferHelper;


    /**
     * 客户端连接的时候触发
     *
     * @param client 客户端
     */
    @OnConnect
    public void onConnect(SocketIOClient client) {
        log.info("客户端建立连接连接:sessionId:{}  param:{}", client.getSessionId(), JSON.toJSONString(client.getHandshakeData().getUrlParams()));
        //客户端本地缓存
        LocalCacheUtil.addLocalClient(client.getHandshakeData().getSingleUrlParam(FROM), client);
        //注册中心注册
        redisTemplate.opsForValue().set(client.getHandshakeData().getSingleUrlParam(FROM), nodeName);
        String eventName = client.getHandshakeData().getSingleUrlParam(EVENT_NAME);
        EventHandlerFactory.getEventHandler(eventName).preHandle(client);
    }

    /**
     * 触发事件的baseEvent，具体的业务处理逻辑在用户自定义在handler中实现
     *
     * @param client  客户端
     * @param wrapper 待接受实体包装器
     */
    public void baseOnEvent(SocketIOClient client, BaseEventWrapper wrapper) {
        log.info("客户端触消息交互事件:sessionId:{}  param:{}", client.getSessionId(), JSON.toJSONString(client.getHandshakeData().getUrlParams()));

        //获取到需要发送的地址
        String to = client.getHandshakeData().getSingleUrlParam(TO);
        //确定是否做事件转移
        //如果在当前jvm上，本地处理即可
        if (null != LocalCacheUtil.getLocalClient(to)) {
            String eventName = client.getHandshakeData().getSingleUrlParam(EVENT_NAME);
            log.info("监听到时间名称 eventName={}", eventName);
            EventHandlerFactory.getEventHandler(eventName).doHandle(client, wrapper);
        } else {
            if (null != redisTemplate.opsForValue().get(to)) {
                transferHelper.transfer(redisTemplate.opsForValue().get(to), JSON.toJSONString(wrapper));
                log.info("事件转移");
            }
        }
    }


    /**
     * 断开连接触发事件
     *
     * @param client 客户端
     */
    @OnDisconnect
    public void onDisconnect(SocketIOClient client) {
        //清除客户端本地缓存
        LocalCacheUtil.removeClient(client.getSessionId().toString());
        //注册中心删除信息
        redisTemplate.delete(client.getSessionId().toString());
        String eventName = client.getHandshakeData().getSingleUrlParam(EVENT_NAME);
        EventHandlerFactory.getEventHandler(eventName).afterHandle(client);
    }
}